/*+
________________________________________________________________________

 (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
 Author:	Helene
 Date:		February 2014
________________________________________________________________________

-*/

#include "uielasticmodelprov.h"

#include "ioobjctxt.h"
#include "uigeninput.h"
#include "uimsg.h"
#include "uiseissel.h"
#include "uiveldesc.h"



static const char* inpsourceacstrs[] =
{
    "PWave, Density",
    "Acoustic Impedance, (Density)",
    0
};

static const char* inpsourceelstrs[] =
{
    "P-wave, S-wave, Density",
    "Acoustic Impedance, Shear Impedance, (Density)",
    0
};


uiElasticModelProvider::uiElasticModelProvider( uiParent* p, bool is2d )
    : uiGroup( p, "ElasticModelProvider setup" )
{

    inptypefld_ = new uiGenInput( this, tr("Input type"),
				  BoolInpSpec(true, uiStrings::sAcoustic(),
					      uiStrings::sElastic()) );
    inptypefld_->valuechanged.notify(
			    mCB(this,uiElasticModelProvider,inpTypeSel) );

    const uiString inpsrcstr = tr("Input Source");
    inpsourceacfld_ = new uiGenInput( this, inpsrcstr,
				      StringListInpSpec(inpsourceacstrs) );
    inpsourceacfld_->valuechanged.notify(
			    mCB(this,uiElasticModelProvider,sourceSel) );
    inpsourceacfld_->attach( alignedBelow, inptypefld_ );

    inpsourceelfld_ = new uiGenInput( this, inpsrcstr,
				      StringListInpSpec(inpsourceelstrs) );
    inpsourceelfld_->valuechanged.notify(
			    mCB(this,uiElasticModelProvider,sourceSel) );
    inpsourceelfld_->attach( alignedBelow, inptypefld_ );

    IOObjContext pwctxt = uiVelSel::ioContext();
    pwctxt.forread_ = true;
    uiSeisSel::Setup pwsu( false, false );
    pwsu.seltxt( tr("P-wave Velocity cube") );
    pwavefld_ = new uiVelSel( this, pwctxt, pwsu );
    pwavefld_->attach( alignedBelow, inpsourceacfld_ );

    IOObjContext swctxt = uiVelSel::ioContext();
    swctxt.forread_ = true;
    uiSeisSel::Setup swsu( false, false );
    swsu.seltxt( tr("S-wave Velocity cube") );
    swavefld_ = new uiVelSel( this, swctxt, swsu );
    swavefld_->attach( alignedBelow, pwavefld_ );

    IOObjContext aictxt =
		uiSeisSel::ioContext( is2d?Seis::Line:Seis::Vol, true );
    aictxt.forread_ = true;
    uiSeisSel::Setup aisu( is2d, false );
    aisu.seltxt( tr("Acoustic Impedance") );
    aifld_ = new uiSeisSel( this, aictxt, aisu );
    aifld_->attach( alignedBelow, inpsourceacfld_ );

    IOObjContext sictxt =
		uiSeisSel::ioContext( is2d?Seis::Line:Seis::Vol, true );
    sictxt.forread_ = true;
    uiSeisSel::Setup sisu( is2d, false );
    sisu.seltxt( tr("Shear Impedance") );
    sifld_ = new uiSeisSel( this, sictxt, sisu );
    sifld_->attach( alignedBelow, aifld_ );

    IOObjContext denctxt =
		uiSeisSel::ioContext( is2d?Seis::Line:Seis::Vol, true );
    denctxt.forread_ = true;
    uiSeisSel::Setup su1( is2d, false );
    su1.seltxt( uiStrings::sDensity() );
    densityfld_ = new uiSeisSel( this, denctxt, su1 );
    densityfld_->attach( alignedBelow, sifld_ );

    IOObjContext optdenctxt =
		uiSeisSel::ioContext( is2d?Seis::Line:Seis::Vol, true );
    optdenctxt.forread_ = true;
    uiSeisSel::Setup su2( is2d, false );
    su2.optional_= true;
    su2.seltxt( uiStrings::sDensity() );
    optdensityfld_ = new uiSeisSel( this, optdenctxt, su2 );
    optdensityfld_->attach( alignedBelow, sifld_ );

    inpTypeSel(0);
    sourceSel(0);
    setHAlignObj( inptypefld_ );
}


void uiElasticModelProvider::inpTypeSel( CallBacker* cb )
{
    const bool isac = inptypefld_->getBoolValue();
    inpsourceacfld_->display( isac );
    inpsourceelfld_->display( !isac );
    sourceSel(0);
}


void uiElasticModelProvider::sourceSel( CallBacker* cb )
{
    const bool isac = inptypefld_->getBoolValue();
    const bool needai = isac ? inpsourceacfld_->getIntValue() == 1
			     : inpsourceelfld_->getIntValue() == 1;

    optdensityfld_->display( needai );
    densityfld_->display( !needai );
    aifld_->display( needai );
    sifld_->display( needai && !isac );
    pwavefld_->display( !needai );
    swavefld_->display( !needai && !isac );
}


void uiElasticModelProvider::setInputMIDs(
	const DBKey& pwmid, const DBKey& swmid, const DBKey& aimid,
	const DBKey& simid, const DBKey& denmid )
{
    const bool iselastic = simid.isValid() || swmid.isValid();
    const int sourceoptidx = aimid.isInvalid() ? 0 : 1;
    inptypefld_->setValue( !iselastic );
    inpsourceacfld_->display( !iselastic );
    inpsourceelfld_->display( iselastic );
    if ( iselastic )
	inpsourceelfld_->setValue( sourceoptidx );
    else
	inpsourceacfld_->setValue( sourceoptidx );

    sourceSel( 0 );

    pwavefld_->setInput( pwmid );
    swavefld_->setInput( swmid );
    aifld_->setInput( aimid );
    sifld_->setInput( simid );
    densityfld_->setInput( denmid );
    optdensityfld_->setChecked( denmid.isValid() );
}


bool uiElasticModelProvider::getInputMIDs( DBKey& pwmid, DBKey& swmid,
					   DBKey& aimid, DBKey& simid,
					   DBKey& denmid ) const
{
    pwmid = pwavefld_->attachObj()->isDisplayed() ? pwavefld_->key()
						  : DBKey::getInvalid();
    swmid = swavefld_->attachObj()->isDisplayed() ? swavefld_->key()
						 : DBKey::getInvalid();
    aimid = aifld_->attachObj()->isDisplayed() ? aifld_->key()
					       : DBKey::getInvalid();
    simid = sifld_->attachObj()->isDisplayed() ? sifld_->key()
					       : DBKey::getInvalid();

    const bool isac = inptypefld_->getBoolValue();
    const bool needsi = !isac && inpsourceelfld_->getIntValue() == 1;
    const bool needai = isac ? inpsourceacfld_->getIntValue() == 1
			     : inpsourceelfld_->getIntValue() == 1;

    denmid = needai ? optdensityfld_->isChecked() ? optdensityfld_->key()
						  : DBKey::getInvalid()
		    : densityfld_->key();

    uiString basestr  = tr("Selected inputs are not in adequation with "
			    "chosen model type and source");
    uiStringSet missingvals;
    missingvals.setEmpty();
    if ( needai && aimid.isInvalid() )
	missingvals = tr("Acoustic Impedance");

    if ( needsi && simid.isInvalid() )
	missingvals = tr("Shear Impedance");

    if ( !needai && denmid.isInvalid() )
	missingvals += tr("Density Inpedance");

    if ( !needai && pwmid.isInvalid() )
	missingvals += tr("P-Wave");

    if ( !isac && !needsi && swmid.isInvalid() )
	missingvals += tr("S-Wave");
    uiString reasonstr;
    if ( missingvals.size() > 1 )
	reasonstr = tr("%1 inputs are missing").arg(missingvals
							.createOptionString());
    else if ( missingvals.size() == 1 )
	reasonstr = tr("%1 input is misisng").arg(missingvals
							.createOptionString());
    else
    if ( !reasonstr.isEmpty() )
    {
	const_cast<uiElasticModelProvider*>(this)->errmsg_ = basestr;
	const_cast<uiElasticModelProvider*>(this)->
			errmsg_.appendPhrase( reasonstr );
	return false;
    }

    return true;
}
